/*

* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Smart-Shop开源商城系统/ Java商城-首选电商平台系统 请务必保留此注释头信息
* |     开源地址: https://gitee.com/ningbo-qishan/gruul-mall
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     可正常分享和学习源码,未经授权 不可商用！
* |     商业版中台购买/开源版商业授权 联系技术客服
* |     官网:  https://www.73app.cn/
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Copyright (c) 2016-2999 宁波启山智软科技有限公司
* |     版权所有 ,侵权必究！
* ------------------------------------------------------------------------

*/
package com.medusa.gruul.solitaire.service.manager.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.gruul.common.core.constant.CommonConstants;
import com.medusa.gruul.common.core.exception.ServiceException;
import com.medusa.gruul.common.core.util.Result;
import com.medusa.gruul.common.core.util.SystemCode;
import com.medusa.gruul.common.data.tenant.TenantContextHolder;
import com.medusa.gruul.platform.api.feign.RemoteMiniInfoService;
import com.medusa.gruul.platform.api.model.dto.MiniAuthInfoDto;
import com.medusa.gruul.solitaire.api.entity.SolitaireWeChatBot;
import com.medusa.gruul.solitaire.api.entity.SolitaireWeChatGroup;
import com.medusa.gruul.solitaire.api.model.param.manager.SolitaireWeChatBotParam;
import com.medusa.gruul.solitaire.mapper.manager.SolitaireWeChatBotMapper;
import com.medusa.gruul.solitaire.mapper.manager.SolitaireWeChatGroupMapper;
import com.medusa.gruul.solitaire.service.manager.ISolitaireWeChatBotService;
import com.medusa.gruul.solitaire.wechat.WeChatBot;
import com.medusa.gruul.solitaire.wechat.config.ActiveDelaySendJobHandler;
import com.medusa.gruul.solitaire.wechat.constant.ResponseCode;
import com.medusa.gruul.solitaire.wechat.model.Account;
import com.medusa.gruul.solitaire.wechat.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


/**
 * <p>
 * 接龙信息设置 服务实现类
 * </p>
 *
 * @author lcysike
 * @since 2020-06-09
 */
@Service
public class SolitaireWeChatBotServiceImpl extends ServiceImpl<SolitaireWeChatBotMapper, SolitaireWeChatBot> implements ISolitaireWeChatBotService {

    @Resource
    private RemoteMiniInfoService remoteMiniInfoService;

    @Autowired
    private SolitaireWeChatBotMapper solitaireWeChatBotMapper;

    @Autowired
    private SolitaireWeChatGroupMapper solitaireWeChatGroupMapper;


    @Resource
    private ActiveDelaySendJobHandler activeDelaySendJobHandler;

    private static Map<String,Long> lastMsgTimeMap = new ConcurrentHashMap<>();

    /**
     * 请求微信机器人接口
     * @return Result
     */
    @Override
    public Result wxLogin() {
        String tenantId = TenantContextHolder.getTenantId();
        MiniAuthInfoDto miniAuthInfo = remoteMiniInfoService.getMiniAuthInfo(tenantId).getData();
        if(BeanUtil.isEmpty(miniAuthInfo)){
            throw new ServiceException("无效的店铺，请联系客服！", SystemCode.DATA_EXISTED.getCode());
        }
        String appModelId = miniAuthInfo.getAppId();
        WeChatBot weChatBot = WeChatBotFactory.getWeChatBotBean(appModelId);
        MyBot.activeDelaySendJobHandler = activeDelaySendJobHandler;
        startLogin(appModelId);
        DateUtils.sleep(1000);
        return Result.ok().setData(weChatBot.setSuffix);

    }

    /**
     * 获取群聊列表
     * @param solitaireWeChatBotParam
     * @return String
     */
    @Override
    public Result getGroupList(SolitaireWeChatBotParam solitaireWeChatBotParam) {
        String appModelId = getAppModelId();
        List<Account> indexGroupList = WeChatBotFactory.getWeChatBotBean(appModelId).api().getIndexGroupList();
        if(CollectionUtil.isNotEmpty(indexGroupList)){
            List<String> data = indexGroupList.stream()
                    .filter(o -> StringUtils.isNotEmpty(o.getNickName()))
                    .map(o -> WeChatUtils.emojiParse(o.getNickName()))
                    .collect(Collectors.toList());
            //过滤掉已绑定的群聊
            data=filterBindGroup(appModelId,solitaireWeChatBotParam.getBotUin(), data);
            IPage<String> page = new Page<>(solitaireWeChatBotParam.getCurrent(), solitaireWeChatBotParam.getSize());
            page.setRecords(data);
            return Result.ok(page);
        }
        return Result.failed("没有数据");
    }

    /**
     * 获取群聊列表
     * @param solitaireWeChatBotParam
     * @return String
     */
    @Override
    public Result searchGroupList(SolitaireWeChatBotParam solitaireWeChatBotParam) {
        String appModelId = getAppModelId();
        List<Account> indexGroupList = WeChatBotFactory.getWeChatBotBean(appModelId).api().getIndexGroupList();
        if(CollectionUtil.isNotEmpty(indexGroupList)){
            List<String> data = indexGroupList.stream()
                    .filter(o -> StringUtils.isNotEmpty(o.getNickName()))
                    .map(o -> WeChatUtils.emojiParse(o.getNickName()))
                    .collect(Collectors.toList());
            //过滤掉已绑定的群聊
            data=filterBindGroup(appModelId,solitaireWeChatBotParam.getBotUin(), data);
            data = data.stream().filter(o->o.contains(solitaireWeChatBotParam.getGroupName())).collect(Collectors.toList());
            IPage<String> page = new Page<>(solitaireWeChatBotParam.getCurrent(), solitaireWeChatBotParam.getSize());
            page.setRecords(data);
            return Result.ok(page);
        }
        return Result.failed("没有数据");
    }

    /**
     * 检查机器人登录状态
     * @return Result
     */
    @Override
    public Result checkLogin() {
        String appModelId = getAppModelId();
        WeChatBot weChatBot = WeChatBotFactory.getWeChatBotBean(appModelId);
        if (weChatBot.getLoginSuccess()) {
            String icon = weChatBot.api().downloadHeadImg(weChatBot.session().getUserName());
            Map<String, String> data = new HashMap<>(8);
            data.put("nickName", WeChatUtils.emojiParse(weChatBot.session().getNickName()));
            data.put("uin", weChatBot.session().getWxUin());
            data.put("icon", icon.replace("/data/webFile",""));
            //将所有机器人的在线状态改为离线
            new LambdaUpdateChainWrapper<>(solitaireWeChatBotMapper)
                    .set(SolitaireWeChatBot::getOnline, CommonConstants.NUMBER_ZERO).update();
            SolitaireWeChatBot bot = solitaireWeChatBotMapper.selectById(Long.valueOf(data.get("uin")));
            if (bot == null) {
                bot = new SolitaireWeChatBot();
                bot.setBotNickName(data.get("nickName"));
                bot.setBotUin(Long.valueOf(data.get("uin")));
                bot.setOnline(CommonConstants.NUMBER_ONE);
                bot.setBotIcon(data.get("icon"));
                bot.setLastLoginDate(new Date());
                int insert = this.solitaireWeChatBotMapper.insert(bot);
                if(insert == 0){
                    throw new ServiceException("机器人登录失败", SystemCode.DATA_ADD_FAILED.getCode());
                }
            }else {
                bot.setBotNickName(data.get("nickName"));
                bot.setBotUin(Long.valueOf(data.get("uin")));
                bot.setOnline(CommonConstants.NUMBER_ONE);
                bot.setBotIcon(data.get("icon"));
                bot.setLastLoginDate(new Date());
                int update = this.solitaireWeChatBotMapper.insert(bot);
                if(update == 0){
                    throw new ServiceException("机器人登录失败", SystemCode.DATA_ADD_FAILED.getCode());
                }
            }
            return Result.ok(bot);
        }else if(weChatBot.scanStatus()){
            throw new ServiceException("请在手机上确认登录", ResponseCode.PLEASE_LOGIN);
        }  else if (weChatBot.isGeneratorQr()) {
            throw new ServiceException("请扫码", ResponseCode.PLEASE_CHECK);
        }else {
            if (weChatBot.getIsLoggedIn() != null && weChatBot.getIsLoggedIn()){
                throw new ServiceException("初始化中。。。", ResponseCode.INITING);
            }else {
                throw new ServiceException("请登陆", ResponseCode.PLEASE_LOGIN);
            }
        }
    }

    /**
     * 删除机器人
     */
    @Override
    public void removeBotByUin(Long botUin) {
        solitaireWeChatBotMapper.deleteById(botUin);
        solitaireWeChatGroupMapper.delete(new QueryWrapper<SolitaireWeChatGroup>().eq("bot_id", botUin));
    }

    /**
     * 获取租户id对应的小程序id
     */
    public String getAppModelId(){
        String tenantId = TenantContextHolder.getTenantId();
        MiniAuthInfoDto miniAuthInfo = remoteMiniInfoService.getMiniAuthInfo(tenantId).getData();
        if(BeanUtil.isEmpty(miniAuthInfo)){
            throw new ServiceException("无效的店铺，请联系客服！", SystemCode.DATA_EXISTED.getCode());
        }
        return miniAuthInfo.getAppId();
    }

    /**
     * 过滤已绑定群聊信息
     */
    private List<String> filterBindGroup(String appModelId, Long botUin, List<String> groupNames){
        SolitaireWeChatBot bot = solitaireWeChatBotMapper.selectById(botUin);
        if(BeanUtil.isEmpty(bot)){
            throw new ServiceException("机器人信息获取失败！", SystemCode.DATA_EXISTED.getCode());
        }
        Long botId = bot.getId();
        //过滤掉已绑定的群聊
        List<SolitaireWeChatGroup> solitaireWeChatGroups = solitaireWeChatGroupMapper.selectList(new QueryWrapper<SolitaireWeChatGroup>().eq("bot_id", botId).eq("is_deleted", 0));
        List<String> bindGroups = solitaireWeChatGroups.stream().map(SolitaireWeChatGroup::getGroupName)
                .collect(Collectors.toList());
        return groupNames.stream().filter(o->!bindGroups.contains(o)).collect(Collectors.toList());
    }

    private void startLogin(final String appModelId){
        final WeChatBot weChatBotBean = WeChatBotFactory.getWeChatBotBean(appModelId);
        //正在登录中则不会启动新的登录线程
        if (!weChatBotBean.getLogining() && !weChatBotBean.getIsLoggedIn()){
            ThreadPool.getThreadPool().execute(() -> weChatBotBean.start());
        }
    }

    public Result sendMsgsendMsgByName(String appModelId,String groupNickName,String msg){
        //对消息发送频率进行限制，1秒只能发送一条消息
        Long lastTime = lastMsgTimeMap.get(appModelId);
        if (lastTime == null){
            lastTime = System.currentTimeMillis();
        }else {
            Long now = System.currentTimeMillis();
            synchronized (SolitaireWeChatBotServiceImpl.class){
                if ((now-lastTime)<1000L){
                    DateUtils.sleep(1000L-(now-lastTime));
                }
                lastTime = System.currentTimeMillis();
            }
        }
        lastMsgTimeMap.put(appModelId,lastTime);
        WeChatBot weChatBotBean = WeChatBotFactory.getWeChatBotBean(appModelId);
        boolean sendFlag = weChatBotBean.sendMsgByGroupName(groupNickName, msg);
        return sendFlag ? Result.ok("消息发送成功") : Result.failed("消息发送失败");
    }

    @Override
    public Result logout(){
        String appModelId = getAppModelId();
        WeChatBotFactory.getWeChatBotBean(appModelId).api().logout();
        return Result.ok();
    }
}
